package com.hup.minicontroller.client.view.main;

import com.hup.minicontroller.client.constant.AppConstant;
import com.hup.minicontroller.client.model.AppConfig;
import com.hup.minicontroller.client.model.AppState;
import com.hup.minicontroller.client.model.LanBroadcastServer;
import com.hup.minicontroller.client.model.ScannedServerItem;
import com.hup.minicontroller.client.mvp.MainMvp.IMainView;
import com.hup.minicontroller.client.mvp.MainMvp.MainPresenter;
import com.hup.minicontroller.client.service.LanClientService;
import com.hup.minicontroller.client.view.connected.ConnectedFrame;
import com.hup.minicontroller.client.view.main.ScannedServerItemForm.ConnectListener;
import com.hup.minicontroller.common.util.NetUtil;
import com.hup.utils.commons.start.DialogHelper;
import com.hup.utils.commons.start.LookThemeUtil;
import com.hup.utils.commons.start.SimpleExitHandler;
import com.hup.utils.commons.start.SpringContext;
import com.hup.utils.io.netty.model.LoginResponsePacket;
import com.hup.utils.swing.ComponentUtil;
import com.hup.utils.swing.frame.BaseFrame;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;

/**
 * @author hugan
 * @date 2021/5/23
 */
@Log4j2
@Component
public class MainFrame extends BaseFrame implements IMainView {

    private final AppState appState;
    private final MainPresenter presenter;
    private final LanClientService lanClient;
    private final ArrayList<ScannedServerItem> lstScannedServer;

    private MainForm form;
    private ConnectingDialog connectingDialog;
    private ConnectListener lanConnectBtnListener;

    public MainFrame(MainPresenter presenter, AppState appState, LanClientService lanClient) {
        super(AppConstant.APP_TITLE);
        this.appState = appState;
        this.presenter = presenter;
        this.lanClient = lanClient;
        lstScannedServer = new ArrayList<>();

        initView();
        initListener();
    }

    private void initView() {
        form = new MainForm();
        setContentPane(form.root);
        pack();
        setSize(getWidth(), (int) (LookThemeUtil.getScreenScale() * 500));
        setLocationRelativeTo(null);
        form.txtHotspotGateway.setText(NetUtil.getGatewayIp("127.0.0.1"));
    }

    private void initListener() {
        form.btnConnectLan.addActionListener(e -> doConnectLan());
        //点击背景刷新网关
        form.btnConnectHotspot.getParent().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                form.txtHotspotGateway.setText(NetUtil.getGatewayIp("127.0.0.1"));
            }
        });
        form.btnConnectHotspot.addActionListener(e -> {
            form.txtToConnect.setText(form.txtHotspotGateway.getText());
            doConnectLan();
        });
        lanConnectBtnListener = item -> {
            if (item.isLan()) {
                String address = item.getLanBroadcastServer().getAddress();
                form.txtToConnect.setText(address);
                doConnectLan();
            } else {
                //appState.getAppConfig().setBluetoothServer(item.getBluetoothDevice());
                //waitingDialog = WaitingDialog.show(MainActivity.this, "连接中");
                //subThreadHandler.post(() -> bluetoothClient.switchClient(true));
            }
        };
    }

    @Override
    public void onHidden(boolean dispose) {
        log.debug("dispose={}", dispose);
        if (dispose) {
            SpringContext.getBean(SimpleExitHandler.class).doExit();
        }
    }

    @Override
    public void onConnectResult(LoginResponsePacket loginResponse) {
        runOnUiThread("处理连接结果", () -> {
            if (connectingDialog != null) {
                connectingDialog.dispose();
                connectingDialog = null;
            }
            if (loginResponse != null && !loginResponse.isSuccess() && loginResponse.getErrorMessage() != null) {
                DialogHelper.confirm(loginResponse.getErrorMessage()).error().show();
            }
            boolean connected = appState.getConnectedType() != null;
            ConnectedFrame.switchVisible(this, connected);
        });
    }

    @Override
    public void onConnectionLost() {
        onConnectResult(null);
    }

    @Override
    public void onChannelIdle() {
    }

    @Override
    public void onScannedBroadcastServer(Collection<LanBroadcastServer> broadcastServers) {
        if (!isVisible()) return;
        runOnUiThread("更新服务端列表", () -> {
            lstScannedServer.removeIf(ScannedServerItem::isLan);
            lstScannedServer.addAll(0, ScannedServerItem.cast(broadcastServers));//在列表前面
            //log.info("lstScannedServer={}", lstScannedServer);
            form.pScannedServer.removeAll();
            for (int i = 0, lstScannedServerSize = lstScannedServer.size(); i < lstScannedServerSize; i++) {
                ScannedServerItem item = lstScannedServer.get(i);
                ScannedServerItemForm itemForm = new ScannedServerItemForm();
                itemForm.setConnectListener(lanConnectBtnListener);
                itemForm.setServer(item);
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridx = 0;
                gbc.gridy = i;
                gbc.weightx = 1.0;
                gbc.fill = GridBagConstraints.BOTH;
                form.pScannedServer.add(itemForm, gbc);
            }
            ComponentUtil.afterChangedChild(form.pScannedServer);
        });
    }

    private void doConnectLan() {
        log.info("");
        connectingDialog = ConnectingDialog.create(this, "连接中");
        doInBackground("连接", () -> {
            AppConfig appConfig = appState.getAppConfig();
            appConfig.setLanInputIp(form.txtToConnect.getText());
            appConfig.save();
            lanClient.switchClient(true);
        });
        connectingDialog.setVisible(true);
    }

    public JFrame initConfig() {
        form.txtToConnect.setText(appState.getAppConfig().getLanInputIp());
        return this;
    }
}
